#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#
# Wireless-Tools support
# Copyright (c) 2011 Paulo Matias
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

import subprocess, re, os

def _popen(args):
    env = dict(os.environ)
    env['LANG'] = 'C'
    return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)

class WTools():
    def __init__(self):
        self._dev = self._find_device()
        if self._dev == None:
            raise Exception, 'Unable to find a wireless device'
        self._dhcp = self._find_dhcp()
        if self._dhcp == None:
            raise Exception, 'Unable to find a dhcp client'
        
    def scan(self):
        p = _popen(['sudo', 'ifconfig', self._dev, 'up'])
        p.wait()
        p = _popen(['sudo', 'iwlist', self._dev, 'scan'])
        ssid = bssid = strength = None
        for line in p.stdout.xreadlines():
            m = re.search(r'^\s*Cell\s+\d+\s+-\s+Address:\s+([0-9A-F:]{17})', line)
            if m: bssid = m.group(1)
            m = re.search(r'^\s*Quality=(\d+)/(\d+)', line)
            if m: strength = int(100*int(m.group(1))/int(m.group(2)))
            m = re.search(r'^\s*ESSID:"(.*?)"', line)
            if m:
                ssid = m.group(1)
                yield (ssid, bssid, strength)
                
    def connect(self, ssid, bssid=None):
        p = _popen(['sudo', 'ifconfig', self._dev, 'up'])
        p.wait()
        args = ['sudo', 'iwconfig', self._dev, 'essid', ssid]
        if bssid:
            args += ['ap', bssid]
        p = _popen(args)
        p.wait()
        if self._dhcp == 'dhcpcd':
            p = _popen(['sudo', 'dhcpcd', '-k', self._dev])
            p.wait()
        p = _popen(['sudo', self._dhcp, self._dev])
        p.wait()
                
    def current_ap(self):
        p = _popen(['iwconfig', self._dev])
        data = p.stdout.read()
        m = re.search(r'ESSID:"(.*?)"', data)
        if m == None: return None
        ssid = m.group(1)
        m = re.search(r'Access Point:\s+([0-9A-F:]{17})', data)
        if m == None: return None
        bssid = m.group(1)
        strength = 0
        m = re.search(r'Quality=(\d+)/(\d+)', data)
        if m: strength = int(100*int(m.group(1))/int(m.group(2)))
        return (ssid, bssid, strength)
            
    def _find_device(self):
        p = _popen(['iwconfig'])
        for line in p.stdout.xreadlines():
            m = re.search(r'^(.+?)\s+IEEE 802.11', line)
            if m: return m.group(1)
        return None
    
    def _find_dhcp(self):
        path = os.environ['PATH'].split(':')
        for prog in ('dhclient', 'dhcpcd'):
            for d in path:
                if os.path.exists(os.path.join(d,prog)):
                    return prog
        return None
    
if __name__ == '__main__':
    wt = WTools()
    print repr(list(wt.scan()))
    print repr(wt.current_ap())
